package school30.ui.forms;

import java.util.Vector;
import school30.School30App;
import school30.ui.Painter;
import school30.ui.events.FocusEvent;
import school30.ui.events.KeyEvent;

public class Form {

    protected Vector widgets = new Vector();
    protected int focusedWidgetIndex = -1;
    protected Painter painter;
    private final Object lock = new Object();
    private int background;
    private School30App app;

    public Form(School30App s) {
        app = s;
        painter = s.getPainter();
    }

    public void addWidget(Widget w) {
        widgets.addElement(w);
        w.setForm(this);
        if (w.isFocusable() && focusedWidgetIndex == -1) {
            focusedWidgetIndex = widgets.size() - 1;
            w.handleEvent(new FocusEvent(FocusEvent.TYPE_GAINED));
        }
        repaint();
    }

    public int getBackground() {
        return background;
    }

    public void setBackground(int background) {
        this.background = background;
        repaint();
    }

    public int getFocusedWidgetIndex() {
        return focusedWidgetIndex;
    }

    public void setFocusedWidgetIndex(int focusedWidgetIndex) {
        this.focusedWidgetIndex = focusedWidgetIndex;
    }

    public Painter getPainter() {
        return painter;
    }

    public void setPainter(Painter painter) {
        this.painter = painter;
    }

    public Vector getWidgets() {
        return widgets;
    }

    public void setWidgets(Vector widgets) {
        this.widgets = widgets;
    }

    public void repaintWidget(Widget w) {
        for (int i = 0; i < widgets.size(); i++) {
            Widget k = (Widget) widgets.elementAt(i);
            if (k == w) {
                painter.setTranslateX(k.getPosition().getX());
                painter.setTranslateY(k.getPosition().getY());
                k.paint(painter);
                painter.setTranslateX(-k.getPosition().getX());
                painter.setTranslateY(-k.getPosition().getY());
                break;
            }
        }
    }

    public void repaint() {
        painter.setColor(background);
        painter.fillRectangle(0, 0, app.getWidth(), app.getHeight());
        for (int i = 0; i < widgets.size(); i++) {
            Widget k = (Widget) widgets.elementAt(i);
            painter.setTranslateX(k.getPosition().getX());
            painter.setTranslateY(k.getPosition().getY());
            k.paint(painter);
            painter.setTranslateX(-k.getPosition().getX());
            painter.setTranslateY(-k.getPosition().getY());
        }
    }

    public void start() {
        synchronized (lock) {
            try {
                lock.wait();
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    public void keyPressed(int code) {
        if (code == KeyEvent.KEY_STAR)
            nextFocus();
        else if (focusedWidgetIndex >= 0) {
            ((Widget) widgets.elementAt(focusedWidgetIndex)).handleEvent(
                    new KeyEvent(code, KeyEvent.TYPE_PRESSED));
        }
    }

    public void keyReleased(int code) {
        if (focusedWidgetIndex >= 0) {
            ((Widget) widgets.elementAt(focusedWidgetIndex)).handleEvent(
                    new KeyEvent(code, KeyEvent.TYPE_RELEASED));
        }
    }

    public void nextFocus() {
        for (int i = focusedWidgetIndex + 1; i < widgets.size(); i++) {
            Widget w = (Widget) widgets.elementAt(i);
            if (w.isFocusable()) {
                changeFocusTo(i);
                return;
            }
        }
        for (int i = 0; i < focusedWidgetIndex; i++) {
            Widget w = (Widget) widgets.elementAt(i);
            if (w.isFocusable()) {
                changeFocusTo(i);
                return;
            }
        }
    }

    public void changeFocusTo(int i) {
        ((Widget) widgets.elementAt(focusedWidgetIndex)).handleEvent(
                new FocusEvent(FocusEvent.TYPE_LOSED));
        focusedWidgetIndex = i;
        ((Widget) widgets.elementAt(focusedWidgetIndex)).handleEvent(
                new FocusEvent(FocusEvent.TYPE_GAINED));
        repaint();
    }
}
